///<reference path="Util.js"/>
///<reference path="MSArray.js"/>
//To check for vsdoc: http://ajax.microsoft.com/ajax/jQuery/jquery-1.4.2-vsdoc.js
function MNovaUtil(selector)
{
/// <summary>1: Update the window
/// 1.1 - MNovaUtil()
/// 2: Find the item or items based on the selector string.
/// 2.1 - MNovaUtil("S")
/// 2.2 - MNovaUtil("S 1")
/// 2.3 - MNovaUtil("S PT")</summary>
///<param name="selector" type="String">String to find an item in the MNova app</param>
///<returns type="MNovaUtil">the found object</returns>

//more types: Function Date Int Object Boolean
//example: <param name="callback" type="Function">The function that will be executed on every object.</param>
		// <returns type="Number" />
		// <param name="elem" type="Object">The value to search for.</param>
		// <param name="array" type="Array">An array through which to search.</param>

	 this.version = "0.0.2";
	 this.excepts = 4657;

	 this.checkVersion(this.excepts);

	   this.window = mainWindow.activeDocument;
	   this.page = new Page(this.window.curPage());
	   this.pageOffest = {};
	   this.pageOffest.top = this.page.top;
	   this.pageOffest.left = this.page.left;
	   this.pageOffest.right = this.page.right;
	   this.pageOffest.width = this.pageOffest.right - this.pageOffest.left;
	   this.pageOffest.bottom = this.page.bottom;
	   this.pageOffest.height = this.pageOffest.bottom - this.pageOffest.top;
	   this.defaultDialogs();
	   //$ = this; //can use $.page or $.ShowDialog('ChooseFormat')

	  if ( !selector ) {
		this.window.update();
			return this;
		}

		// Handle HTML strings
		if ( typeof selector === "string" ) {
			return this.find(selector);
		}
}



//-------------------------------------------------GUI Calls----------------------------------------------------------
//MNovaUtil.clicked(controlItem, "TextBox1", onOpenFile)
MNovaUtil.prototype.clicked = function (source, target, callback) {
	try{
	  this.dialog.widgets[source].clicked.connect(this.dialog.widgets[target],callback);
	}
	catch (err){
	  print("failed to connect source and target for click event");
	}
};

//MNovaUtil.openFileClick("source", "target")
MNovaUtil.prototype.openFileClick = function (source, target) {
	try{
	  this.dialog.widgets[source].clicked.connect(this.dialog.widgets[target],onOpenFile);
	}
	catch (err){
	  print("failed to connect source and target for click event");
	}
};

//Example callback used by MNovaUtil.openFile("s","t")
MNovaUtil.prototype.onOpenFile = function () {

	var fileName = this.text;
	fileName = FileDialog.getSaveFileName(this.filter ? this.filter : "", "Save File", fileName.length ? File.absDirPath(fileName) : Dir.home());
	if (fileName.length){
		this.text = fileName;
	}
};

//MNovaUtil.saveFile("c:/sampleReport","pdf", true)
MNovaUtil.prototype.saveFile = function (filename,format, history) {
		  //	Check if file already exists and ask if user wants to overwrite
		  serialization.fileHistory = history;
		  var f = new File(filename);
		  if(this.fileExists(f))
		  {
				serialization.save(filename,format);
		  }
		  serialization.fileHistory = true;
 };


//-------------------------------------------------NMR & Mass Calls----------------------------------------------------------


MNovaUtil.fn = MNovaUtil.prototype;


MNovaUtil.prototype.checkVersion = function(version)
{
/// <summary>Checks if you can run the feature</summary>
///<param name="version" type="String">The release version of MNova that is required for this feature</param>

	 if (Application.version.revision < version && Application.version.revision !== 0)
	 {
		  MessageBox.critical("Your version of MNova doesn't support all the functionality of the script. Upgrade to the latest version of MNova.");
		  throw "Expected version {0}.  You have version {1}.".format(version,Application.version.revision);
	 }
};

MNovaUtil.prototype.isValidNMR = function(spec){
		  if(spec !== null){

			if(spec.isValid()){ return;}
		  }
		  MessageBox.critical("Not a spectrum", MessageBox.Ok);
		  throw 'Not a valid spectrum';
};

MNovaUtil.prototype.massSpectrum = function(item)
{
/// <summary>1: Read the current spectrum and validate it
/// 1.1 - MNovaUtil.massSpectrum()
/// 2: Read the current spectrum and validate it
/// 2.1 - MNovaUtil.massSpectrum(spectrumItem)</summary>
///<param name="item" type="pageItem">A page item that is a Mass Spectrum</param>
///<returns type="MassSpectrum">the found spectrum object</returns>

		  this.spec = new MassItem(item); //TODO item.rtti() -> type NMR or other...

		  if(this.spec.MassItemInfo.valid===false)
		  {
			MessageBox.critical("Not a spectrum", MessageBox.Ok);
			throw 'Not a valid spectrum';
		  }
		  return this.spec;
};

MNovaUtil.prototype.getParam = function (spec, name) {
/// <summary>1: Read the spectrum parameter
/// 1.1 - MNovaUtil.getParam("Spectrometer Frequency")</summary>
///<param name="name" type="String">Name of spectrum parameter</param>
///<returns type="String">spectrum parameter value</returns>
	spec.getParam(name);
};

MNovaUtil.prototype.AnnotatePeak = function (spec) {
/// <summary>1: Read the spectrum parameter
/// 1.1 - MNovaUtil.getParam("Spectrometer Frequency")</summary>
///<param name="name" type="String">Name of spectrum parameter</param>
///<returns type="String">spectrum parameter value</returns>

	  var peakList = new Peaks(spec.peaks());
	  print(peakList.count);
	  for (var i = 0; i< peakList; i++){
			var peak = new Peak(peakList.at(i));
			print(peak);

			var transCoords = spec.scaleToPage({x:peak.delta(), y:peak.intensity });
			if( transCoords === undefined ) {continue;}

			var arrowEndCoords = {x: transCoords.x-10, y: transCoords.y-10};

			this.arrow({top: transCoords.y, left: transCoords.x, height: -10, width:-10});

			var txt = "Peak (delta: %1, intensity: %2)".format(peak.delta(),peak.intensity);
			var textItem = this.text(txt, {top: transCoords.y, left: transCoords.x});
			this.movePosition(textItem, {top: -textItem.height,  left: -textItem.width/2.0});
	  }
	  spec.update();
	  mainWindow.activeDocument.update();
};

//$.template("C:/DEMO.mnova");
MNovaUtil.prototype.template = function(templateFile){
	  // Check that appropriate layout template document exists.
	  var layoutTemplateDocumentName = templateFile;//"C:/DEMO.mnova";
	  if (!File.exists(layoutTemplateDocumentName))
	  {
		return;
	  }

	  // Apply layout template
	  var tempDw = new DocumentWindow(mainWindow.activeWindow());
	  var oldTemplateHistory = tempDw.templateHistory;
	  tempDw.templateHistory = false;
	  tempDw.applyTemplateDocument(layoutTemplateDocumentName);
	  tempDw.templateHistory = oldTemplateHistory;
};

MNovaUtil.prototype.items = function()
{
/// <summary>1: Read items into an array item(i) -> item[i]
/// 1.1 - MNovaUtil.items()</summary>
///<returns type="Array">Array of items</returns>

	   var count = this.page.itemCount();
	   var i = 0;
	   var itemArray = new Array(count);
	   for(i=0; i<count; i++)
	   {
			   itemArray[i] = this.page.item(i);
	   }
	   return itemArray;
};

//parameters= [['Spec. no.','Comment'],['Exp. no.','EXPNO'],,['Title','Title'],,['Solvent','Solvent'],['Pulse Sequence','Pulse Sequence'],['Nucleus','Nucleus']]
MNovaUtil.prototype.buildParamTable = function(spec, parameters){
/// <summary>1: Creates a table of parameters for output onto the page
/// 1.1 - MNovaUtil.buildParamTable(spectrum, Json)
/// Json is Array or Array [[],[], , []] . NOTE: blanks and strings are allowed instead of inner []...these are output as seperators </summary>
///<param name="spec" type="NMRSpectrum">NMR Spectrum</param>
///<param name="parameters" type="Json">[['Title': 'Param Name'],['Title': 'Param Name'],['Title': 'Param Name']]</param>
///<returns type="string">the string to output in HTML format</returns>

	var params = '<font face="arial", size="2">';

	for (var i=0; i< parameters.length ;i++){
		if(typeof parameters[i] == 'undefined'){
			params += "<br/>";
		}
		else if(parameters[i].length == 2){
			params += "<b>{0}: </b>{1}<br/>".format(parameters[i][0],spec.getParam(parameters[i][1]));
		}
		else{
			params += "{0}<br/>".format(parameters[i]);
		}

	}
	params += "</font>";
	return params;
};


//-----------------------------------------Dialog Extensions ----------------------------------------

//this.show('Settings',
//            function(x){ /*set values & create signals+slots (widget event handlers)*/},
//            function(x){ /*validate user input*/}}
MNovaUtil.prototype.show= function(DialogName,beforeCallback,afterCallback)
{
/// <summary>1: Creates a UI based on MNovaUtil.dialogs['DialogName'] array
/// 1.1 - if (MNovaUtil.show("DialogName")) {print("pressed OK")}
///2: Allows adding of event handlers to listen to UI widget events like clicked
///2.1 - if (MNovaUtil.showWithEvents("DialogName", function(dia){dia.connect(dia, "TextBox1", callback)})) {print("pressed OK")}
///<param name="DialogName" type="String">The name of the dialog which is in the associative array. Example for PopUp: MNovaUtil.dialogs['PopUp']</param>
///<param name="callback" type="Function">callback to add JS event handlers to capture user interaction while UI is dispalyed</param>
///<returns type="Boolean">Press Acceptted button -> True. Press Reject button -> False</returns>
/*  Could be used to set default values for the items...
if(options != null){
 for( prop in options){
	  try{
		  eval("this.widget({0}).text = {1};".format(prop,otpions[prop]));
	  }catch (err) {
		  print("Error in setting {0} with property: {1}".format(item, prop));
		  print("this.widget({0}).text = options.{1};".format(prop,otpions[prop]));
	  }

  }
}
*/
	return this.showString(this.dialogs[DialogName],beforeCallback,afterCallback);
};

MNovaUtil.prototype.showString= function(XMLString,beforeCallback, afterCallback)
{
	this.dailog = Application.loadUi(XMLString);
	if (this.isFunction(beforeCallback)) {  //Check if we need to do the before callback
			beforeCallback.call(this);  //typically this is to set default values for some/all widgets and also connect signels to slots in GUI (onclick events)
	}

	while(true){
		if(!this.dailog.exec()){
		  return false;  //user pressed cancel button so stop everything
		}
		if (this.isFunction(afterCallback)) {
			if (afterCallback.call(this)){
				return true; //all validation was successful
			}
		}
		else{
		  return true; //finish looping without validation
		}
	}
};

//if (MNovaUtil.showFile("file")) {print("pressed OK")}
MNovaUtil.prototype.showFile= function(file)
{
	this.dailog = Application.loadUiFile(file);
	return this.dailog.exec();
};

//MNovaUtil.widget('id').checked
MNovaUtil.prototype.widget= function(name)
{
	try{
	  return this.dailog.widgets[name];
	}
	catch (err){
	  return null;
	}
};

//MNovaUtil.widgetsInfo()
MNovaUtil.prototype.widgetsInfo= function()
{
	print('-- Start Debug Info --');
	try{
	for( var w in this.dailog.widgets){
	  if(w.length > 0){
		print('-----------------');
		print('Widget Name: ' + w);

		try{
		  var item =this.dailog.widgets[w];
		  for( var prop in item){
			if(item.hasOwnProperty(prop) && typeof item[prop] != 'function'){
				print("        Property: " + prop +" = "+ item[prop] );
			}
		  }
		}catch (err) {print("Could not print all properties");}
	  }
	}
	}catch(err1) {print("could not find dialog in scope");}
	print('-- End Debug Info --');
};

//MNovaUtil.clicked('uPickButton','uReportDirectory',function(){ $.widget('uReportDirectory').text = $.pickFolder('NovartisSampleFolder');}/* SourceId, TargetId, Delegate*/ )
MNovaUtil.prototype.clicked= function(source,target,callback){
	this.widget(source).clicked.connect(
				this.widget(target),
				function(){ /*Event Handler Action => Slot */
					  callback.call(this);
				}
			 );
};


//MNovaUtil.dispose() //free up RAM of dialog box
MNovaUtil.prototype.disposeDialog= function()
{
	if(this.dialog){
	 if(this.dialog.widgets){
		this.dailog.widgets.length = 0;
		this.dailog.widgets = null;
	  }
	  this.dailog = null;
	}

};

MNovaUtil.prototype.isFunction = function (obj) {
		/// <summary>Determine if the argument passed is a Javascript function object.
		/// </summary>
		/// <returns type="boolean" />
		/// <param name="obj" type="Object">Object to test whether or not it is a function.</param>

		return toString.call(obj) === "[object Function]";
};

MNovaUtil.prototype.validate = function (widgetName, invalid, errorMessage) {
   if(this.widget(widgetName).text == invalid){
		  MessageBox.warning(errorMessage, MessageBox.Ok);
		  throw 'Validation Failed'; /*Repeat the dialog box, because invalid user input*/
   }
};

MNovaUtil.prototype.validRegex = function (widgetName, validPattern, errorMessage) {
   if(validPattern.test(this.widget(widgetName).text)){
		  MessageBox.warning(errorMessage, MessageBox.Ok);
		  throw 'Validation Failed'; /*Repeat the dialog box, because invalid user input*/
   }
}

MNovaUtil.prototype.validEmail = function(widgetName, errorMessage) {
  var validPattern =/(^[a-z]([a-z_\.]*)@([a-z_\.]*)([.][a-z]{3})$)|(^[a-z]([a-z_\.]*)@([a-z_\.]*)(\.[a-z]{3})(\.[a-z]{2})*$)/i;
  this.validateRegex(widgetName, validPattern, errorMessage);
};
MNovaUtil.prototype.validNumeric = function(widgetName, errorMessage) {
  var validPattern =/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/;
  this.validateRegex(widgetName, validPattern, errorMessage);
};
MNovaUtil.prototype.validInteger = function(widgetName, errorMessage) {
  var validPattern =/(^-?\d\d*$)/;
  this.validateRegex(widgetName, validPattern, errorMessage);
};
MNovaUtil.prototype.validDate = function(widgetName, errorMessage) {
  var validPattern =/^\d{1,2}(\-|\/|\.)\d{1,2}\1\d{4}$/;
  this.validateRegex(widgetName, validPattern, errorMessage);
};

MNovaUtil.prototype.validRange = function(widgetName, minValue, maxValue, errorMessage) {
   var x = parseInt(this.widget(widgetName).text);
   if (x < minValue || x > maxValue){
	  MessageBox.warning(errorMessage, MessageBox.Ok);
	  throw 'Validation Failed'; /*Repeat the dialog box, because invalid user input*/
   }
};
MNovaUtil.prototype.validLength = function(widgetName, length, errorMessage) {
   var x = this.widget(widgetName).text.length;
   if (x != length){
	  MessageBox.warning(errorMessage, MessageBox.Ok);
	  throw 'Validation Failed'; /*Repeat the dialog box, because invalid user input*/
   }
};
MNovaUtil.prototype.validMinMaxLength = function(widgetName, minLength, maxLength, errorMessage) {
   var x = this.widget(widgetName).text.length;
   if (x < minLength || x > maxLength){
	  MessageBox.warning(errorMessage, MessageBox.Ok);
	  throw 'Validation Failed'; /*Repeat the dialog box, because invalid user input*/
   }
};

MNovaUtil.prototype.validNotEmpty = function(widgetName, errorMessage) {

   var strTemp = trimAll(this.widget(widgetName).text);
   if(strTemp.length > 0){
	 return;
   }
   MessageBox.warning(errorMessage, MessageBox.Ok);
   throw 'Validation Failed'; /*Repeat the dialog box, because invalid user input*/
};


//-----------------------------------------File IO Extensions-------------------------------------------

//If file exists show replace dialog box.  Returns true if want to save ...returns flase if do not replace.
MNovaUtil.prototype.fileExists = function(fileReference)
{
		if(fileReference.exists)
		{
			if(this.show("FileExists"))
		  return true;
			else
		return false;
		}
		else
	  return true;
};
//MNovaUtil.loadLogo(filename)
MNovaUtil.prototype.loadLogo = function(filename)
{
	serialization.fileHistory = false;
	serialization.open(filename); // potentially last item in items array...  //TODO
	serialization.fileHistory = true;
};


MNovaUtil.prototype.getFilename = function(path){
  try{
		var list;
		if(path.indexOf('/') != -1){
			list = path.split('/');
		}
		else{
		  list = path.split('\\');
		}
		for(var i=0;i< list.length;i++){
			if(list[i].indexOf('.raw') != -1 || list[i].indexOf('.RAW') != -1) return list[i];
		}
		return list[list.length - 1]; //return last item in path
	  }catch (err) {return list[list.length - 1]}
};

MNovaUtil.prototype.getFilenameWithoutExtension = function(path){
try{
  var n = this.getFilename(path);
  return n.substring(0,n.length - 4);
 }catch(err) {return null;}
};


//Create a new Document and clone the current page to the new document
MNovaUtil.prototype.pageCopyToNewDocument = function(){
	//var data = $('P').cloneItems($.items());
	var p = mainWindow.activeDocument.curPage();
	var dw = mainWindow.newDocument();
	dw.clonePages([p]); //needs to be array
	dw.deletePages([dw.page(0)]);

	mainWindow.setActiveWindow(dw);
	return dw;  //dw.close();
};


MNovaUtil.prototype.writeFile =function(fileName, text){
	//var dirSetKey = "ASCII_Export/Dir";
	//var saveDir = settings.value(dirSetKey, Dir.home());
	//var fileName = FileDialog.getSaveFileName("ASCII Files (*.txt)", "", saveDir);
	if (!fileName.length)
		return;

	var fout = new File(fileName);

	//settings.setValue(dirSetKey, fout.absDirPath);

	fout.open(File.WriteOnly);
	var sout = new TextStream(fout);
	sout.write(text);
	fout.close();

};


MNovaUtil.prototype.pickFolder = function(registryName,title){
  title = title || "Pick a Folder";

  var settings = Settings();
  var folder = settings.value( registryName, Dir.home());
  folder = FileDialog.getExistingDirectory( folder, title);
  settings.setValue(registryName, folder);
  return folder;
};

MNovaUtil.prototype.cache = function(registryName,val){
  var settings = Settings();
  if(val == null){
	  return settings.value(registryName,"");
   }
   else{
	  settings.setValue(registryName, val);
   }
};

//-----------------------------------------Page & MNR Spectrum Reporting---------------------------------------------------
//MNovaUtil.text("Title",{top:5, left:30, height:20, width:100});
MNovaUtil.prototype.text = function (text, options) {
	text = text || "<No Text>" ;
	var item = draw.text(text, true);
	this.style(item,options);
	this.offset(item);
	//this.setPosition(item, options);
	return item;
};
//MNovaUtil.arrow({top:5, left:300, height:20, width:100});
MNovaUtil.prototype.arrow = function (options) {
	var item = draw.arrow( options.left, options.top, options.left + options.width, options.top + options.height, true, false);
	//this.translate(options.left, options.top );
	this.style(item,options);
	this.offset(item);
	return item;
};


//MNovaUtil.ellipse({top:5, left:300, height:20, width:100});
MNovaUtil.prototype.ellipse = function (options) {
	var item = draw.ellipse( options.width, options.height);

	this.style(item,options);
	this.offset(item);
	return item;
};

//MNovaUtil.rectangle({top:5, left:300, height:20, width:100});
MNovaUtil.prototype.rectangle = function (options) {
	var item = draw.rectangle( options.width, options.height);
	//this.translate(options.left, options.top );
	this.style(item,options);
	this.offset(item);
	return item;
};

//MNovaUtil.style({color:'red', lineColor:'blue', lineStyle: PageItem.DashLine, opacity:50});
MNovaUtil.prototype.style = function (item, options) {
//lineStyle: {PageItem.DashDotDotLine, PageItem.DashDotLine, PageItem.DashLine, PageItem.DotLine, PageItem.NoLine, PageItem.SolidLine}
	for( prop in options){
	  try{
		  eval("item.{0} = options.{1};".format(prop,prop));
	  }catch (err) {
		  print("Error in Styling {0} with property: {1}".format(item, prop));
		  print("item.{0} = options.{1};".format(prop,prop));
	  }

	}

	return item;
};

//MNovaUtil.offset(item);  //Place on page
MNovaUtil.prototype.offset = function (item) {

	item.bottom += this.pageOffest.top;
	item.right += this.pageOffest.left;
	item.top += this.pageOffest.top;
	item.left += this.pageOffest.left;
};

//MNovaUtil.parseOptions({top:5, left:300, height:20, width:100});
MNovaUtil.prototype.parseOptions = function (options) {

	options = options || {}; //If not set correctly give options a default
	options.top = options.top || 0;
	options.left = options.left ||  0;

	options.top += this.pageOffest.top;
	options.left += this.pageOffest.left;

	return options;
};

//MNovaUtil.setPosition(item, options);
MNovaUtil.prototype.setPosition = function (item, options) {
		var width = item.width,
			height = item.height;

		options = this.parseOptions(options);

		if (item.top < options.top) {
				item.bottom = parseFloat(options.top + height, 10);
				item.top = options.top;

		} else {
			item.top = options.top;
			item.bottom = parseFloat(options.top + height, 10);
		}

		if (item.left < options.left)  {
			item.right = parseFloat(options.left + width, 10);
			item.left = options.left;

		} else {
			item.left = options.left;
			item.right = parseFloat(options.left + width, 10);
		}

		if(typeof options.width != 'undefined'){
		item.width = options.width;
		}
		if(typeof options.height != 'undefined'){
		item.height= options.height;
		}

};


//MNovaUtil.movetPosition(item, {top: 5, left:50});
//MNovaUtil.movetPosition(item, {xShift: 5, yShift:50});
MNovaUtil.prototype.movePosition = function (item, options) {

	var xShift, yShift;

	options.top = options.top || 0;
	options.left = options.left ||  0;

	if (options.xShift) {
		xShift = options.xShift;
	} else {
		xShift = -options.left;
	}
	if (options.yShift) {
		yShift = options.yShift;
	} else {
		yShift = options.top;
	}

	item.translate(xShift, yShift);
};


//MNovaUtil.alert("Failure text - stop script with exception");
MNovaUtil.prototype.alert = function (text) {
	MessageBox.critical(text, MessageBox.Ok);
	throw text;
};

//-------------------------------------------------String Extensions--------------------------------------------------
//"test string".wrap("h4");
String.prototype.wrap = function (format) {
	var str = this;
	return "<{0}>{1}</{0}>".format(format,str);
};

//"String pattern {0} with items {1} and {2}".print("Some Data",5, new Date());
String.prototype.print = function () {
	var formatted = this;
	for(var i= 0; i< arguments.length;i++) {
		formatted = formatted.replace("{" + i + "}", arguments[i]);
	}
	print(formatted);
};
String.prototype.font = function (number) {
	var str = this;
	return "<font face='arial', size='{0}'>{1}</font>".format(number,str);
};

//---------------------------------------Find Items--------------------------------------------------
//used in ctor for parsing parameter:
// Search and return single item or array of items
//Can be used with .forEach() for iterating through arrays
/*
Example of using Array results:
//for each item in the Peak table of the active spectrum output the Peak intensity

$('S PK').forEach(function(item,$){
						print(item.intensity);
				 });


Return Pages - (current page or indexed)
$.find('P') get the current page
$.find('P', 0) get the 1st page
$.find('P', 1) get the 2nd page
$.find('P', 2) get the 3rd page

Return count of items - (current page or indexed)
$.find('? #')  or $.find('? #', 2)       Count All items      (current page and 3rd page)
$.find('S #')  or $.find('S #',0)        Count NMR spectrum   (current page or 1st page)
$.find('MS #') or $.find('MS #',0)       Count Mass spectrum  (current page or 1st page)
$.find('O #')  or $.find('O #',0)        Count OLE item       (current page or 1st page)
$.find('AR #') or $.find('AR v',0)       Count arrow item     (current page or 1st page)
$.find('IM #') or $.find('IM #',0)       Count Image item     (current page or 1st page)
$.find('EL #') or $.find('EL #',0)       Count ellipse item   (current page or 1st page)
$.find('PO #') or $.find('PO #',0)       Count Polygon item   (current page or 1st page)
$.find('RE #') or $.find('RE #',0)       Count rectangle item  (current page or 1st page)
$.find('TE #') or $.find('TE #',0)       Count text item      (current page or 1st page)

Return 1 active item from page - (current page or indexed)
$.find('A')  or $.find('A', 2)       Any active item (current page and 3rd page)
$.find('S')  or $.find('S', 2)       NMR spectrum    (current page and 3rd page)
$.find('MS') or $.find('MS', 2)      Mass item       (current page and 3rd page)
$.find('A')  or $.find('A', 2)       active item     (current page and 3rd page)
$.find('O')  or $.find('O', 2)       OLE item        (current page and 3rd page)
$.find('AR') or $.find('AR', 2)      Arrow item      (current page and 3rd page)
$.find('IM') or $.find('IM', 2)      Image item      (current page and 3rd page)
$.find('EL') or $.find('EL', 2)      Ellipse item    (current page and 3rd page)
$.find('PO') or $.find('PO', 2)      Polygon item    (current page and 3rd page)
$.find('RE') or $.find('RE', 2)      Rectangle item   (current page and 3rd page)
$.find('TE') or $.find('TE', 2)      Text item       (current page and 3rd page)

Return 1 indexed item from page - (current or selected page)
$.find('S 1')  or $.find('S 1',0)        Get 2nd NMR spectrum (current page or 1st page)
$.find('MS 2') or $.find('MS 2',0)       Get 3rd Mass spectrum (current page or 1st page)
$.find('O 2')  or $.find('O 2',0)        Get 3rd OLE item (current page or 1st page)
$.find('AR 0') or $.find('AR 0',0)       Get 1st arrow item (current page or 1st page)
$.find('IM 3') or $.find('IM 3',0)       Get 4th Image item (current page or 1st page)
$.find('EL 9') or $.find('EL 9',0)       Get 10th ellipse item (current page or 1st page)
$.find('PO 2') or $.find('PO 2',0)       Get 3rd Polygon item (current page or 1st page)
$.find('RE 2') or $.find('RE 2',0)       Get 3rd rectangle item (current page or 1st page)
$.find('TE 2') or $.find('TE 2',0)       Get 3rd text item (current page or 1st page)

Returns Array for table items related to the active spectrum - (cannot use page numbers as it is only for the current page)
$.find('S M')     Get Multiplets table for active NMR Spectrum
$.find('S PK')    Get Peak table for active NMR Spectrum
$.find('S GM')    Get GSD Multiplets table for active NMR Spectrum
$.find('S GP')    Get GSD peak table for active NMR Spectrum
$.find('S IN')    Get Integrals table for active NMR Spectrum

Returns Array of table items related to indexed spectrum - (current or selected page)
$.find('S 0 M')  or $.find('S 0 M',1)       Get Multiplet table for 1st NMR Spectrum       (current page or 2nd page)
$.find('S 1 PK') or $.find('S 1 PK',0)      Get Peaks table for 2nd NMR Spectrum           (current page or 1st page)
$.find('S 2 GM') or $.find('S 2 GM',6)      Get GSD Multiplets table for 3rd NMR Spectrum  (current page or 7th page)
$.find('S 1 GP') or $.find('S 1 GP',3)      Get GSD Peaks table for 2nd NMR Spectrum       (current page or 4th page)
$.find('S 0 IN') or $.find('S 0 IN',2)      Get Integrals for 1st NMR Spectrum             (current page or 3rd page)

Returns Array of items form ALL pages
$.find('* P')           array of all page
$.find('* S')           array of all NMR spectrum on all pages

Returns Array of items form SELECTED pages
$.find('@ P')          array of selected pages
$.find('@ A')          array of all selected items on page
$.find('@ S')          array of NMR objects from currently selected pages (if empty array of active NMR)

*********** TO IMPLEMENT ********************
Stacked NMR Spectrum - Returns a inner spectrum inside a stacked spectrum - (current or selected page)
$.find('S 0>0')  or $.find('S 0>0',1)           Get 1st stacked NMR spectrum inside the first Spectrum Stack (current page or 2nd page)
$.find('S 0>1')  or $.find('S 0>1',0)           Get 2nd stacked NMR spectrum inside the first Spectrum Stack (current page or 1st page)
$.find('S 0>2')  or $.find('S 0>2',1)           Get 3rd stacked NMR spectrum inside the first Spectrum Stack (current page or 2nd page)
$.find('S 1>0')  or $.find('S 1>0',5)           Get 1st stacked NMR spectrum inside the second Spectrum Stack (current page or 6th page)
$.find('S 1>1')  or $.find('S 1>1',5)           Get 2nd stacked NMR spectrum inside the second Spectrum Stack (current page or 6th page)
$.find('S 1>2')  or $.find('S 1>2',5)           Get 3rd stacked NMR spectrum inside the second Spectrum Stack (current page or 6th page)

Stacked NMR Spectrum - Returns Array of table items related to indexed spectrum - (current or selected page)
$.find('S 0>0 M')  or $.find('S 0>0 M',1)       Get Multiplet table for 1st child stacked spectrum inside 1st Spectrum           (current page or 2nd page)
$.find('S 0>1 PK') or $.find('S 0>1 PK',0)      Get Peaks table  for 2nd child stacked spectrum inside 1st NMR Spectrum          (current page or 1st page)
$.find('S 0>2 GM') or $.find('S 0>2 GM',6)      Get GSD Multiplets table for 3rd child stacked spectrum inside 1st NMR Spectrum  (current page or 7th page)
$.find('S 0>3 GP') or $.find('S 0>3 GP',3)      Get GSD Peaks table for 4th child stacked spectrum inside 1st NMR Spectrum       (current page or 4th page)
$.find('S 0>4 IN') or $.find('S 0>4 IN',2)      Get Integrals for 5th child stacked spectrum inside 1st Spectrum             (current page or 3rd page)

*/




MNovaUtil.prototype.find = function(selector, page)
{
	  this.found = '';

	  var dw = new DocumentWindow(mainWindow.activeWindow());
	  this.page = mainWindow.activeDocument.page(page) || mainWindow.activeDocument.curPage();

	  var MapType= {
		"MS": "Mass Spectrum",
		"M": "Molecule",
		"S": "NMR Spectrum",
		"O": "OLE Object",
		"AR": "Arrow",
		"IM": "Image",
		"EL": "Ellipse",
		"PO": "Polygon",
		"RE": "Rectangle",
		"TE": "Text"};

	  switch (selector)
	  {
		case 'A': //active item;
				try{
					return dw.getActiveItem();
				}catch (err){
					return null;
				}
		case 'P': //current page
				return dw.curPage();
		case 'Pages': //all page
		case '* P': //all page
				return dw.pages();
		case 'SelPages':
		case '@ P':
				 return dw.selectedPages();
		case 'SelItems':
		case '@ A':
				return dw.selection();
		case 'SelectedNMR':
		case '@ S':
				var selPages = dw.selectedPages();
				if (selPages.length ==0){ selPages = [this.page];}
				var found = [];
				for(var i=0;i< selPages.length;i++){
					try{
						for(var j=0;j< selPages[i].itemCount("NMR Spectrum");j++){
						  found.push( new NMRSpectrum(selPages[i].item(j,"NMR Spectrum")));
						}
					}catch (err) {}
				}
				if (found.length ==0){
					return [ this.find('S') ];
				}else{
				  return found;
				}
				break;
		case '* S':
				var selPages = dw.pages();
				if (selPages.length ==0){ selPages = [this.page];}
				var found = [];
				for(var i=0;i< selPages.length;i++){
					try{
						for(var j=0;j< selPages[i].itemCount("NMR Spectrum");j++){
						  found.push( new NMRSpectrum(selPages[i].item(j,"NMR Spectrum")));
						}
					}catch (err) {}
				}
				if (found.length ==0){
					return [ this.find('S') ];
				}else{
				  return found;
				}
				break;
		case 'S': //current specturm;
		case 'MS': //active Mass spectrum item;
				try{
					if(this.window.itemCount(MapType[selector]) > 0){
						return this.window.getActiveItem(MapType[selector]);
						//var str = "this.found = new {0}(this.window.getActiveItem(MapType[selector]));".format(type.replace(' ',''));
						//print(str);
						//eval(str);
					}
					else{
						return null;
					}
				}catch(err){
					print('No current item');
					return null;
				}

		case 'O':  //active OLE item;
		case 'AR': //active arrow item;
		case 'IM': //active Image item;
		case 'EL': //active ellipseitem;
		case 'PO': //active Polygon item;
		case 'RE': //active rectange item;
		case 'TE': //active text item;
				try{
				  var type = MapType[selector];
				  if (page.itemCount(type) > 0)
				  {
					  var res;
					  var str = "res =  new {0}(this.window.getActiveItem(type));".format(type.replace(' ',''));
					  //print(str);
					  eval(str);
					  return res;
				  }
				  else{
					return null;
				  }
				}catch(err){
				  return null;
				}
		default:
				var parts = selector.split(' ');
				if(parts.length >= 2){
						//$('M 2') or $('P 1') or $('S 0')
						if(parts[1] =='#'){
							switch (parts[0])
							{
								 case 'MS': return this.page.itemCount("Mass Spectrum");
								 case 'Mo': return this.page.itemCount("Molecule");
								 case 'S' : return this.page.itemCount("NMR Spectrum");
								 case 'AR': return this.page.itemCount("Arrow");
								 case 'IM': return this.page.itemCount("Image");
								 case 'EL': return this.page.itemCount("Ellipse");
								 case 'RE': return this.page.itemCount("Rectangle");
								 case 'TE': return this.page.itemCount("Text");
								 case 'O' : return this.page.itemCount("OLE Object");
								 case '?' : return this.page.itemCount();
							 }
						}
						else if(parseInt(parts[1]).toString() != 'NaN'){ //part[1] != NaN is an index value
							var idx = parseInt(parts[1]);
							switch (parts[0])
							{
								case 'P':  //$('P 1') second page
									  if(mainWindow.activeDocument.pageCount() > idx){
										  this.found = dw.page(idx);
									  }
									  else{
										  this.found = null;
									  }

									break;
								case 'S':  //specturm;
								case 'MS': //Mass spectrum item;
								case 'O':  //OLE item;
								case 'AR': //arrow item;
								case 'IM': //Image item;
								case 'EL': //ellipse item;
								case 'PO': //Polygon item;
								case 'RE': //rectange item;
								case 'TE': //text item;
									var type = MapType[parts[0]];
									if (this.page.itemCount(type) > idx)
									{
										var res;
										var str = "res =  new {0}(this.page.item(idx, type));".format(type.replace(' ',''));
										//print(str);
										eval(str);
										return res;
									}
									else{
										return null;
									}
									break;
								case 'M': //$('M 2') 3rd Mol Table
									return dw.getMolTableItem(idx);
									break;
								default:
								  this.found =[];

							}
							return this.found;
						}
						else if (parts[0] == 'S'){
							  if (parseInt(parts[1]).toString() != 'NaN'){
							  // $('S 0 M') or $('S 1 PK') or $('S 2 GM') or $('S 1 GP') or $('S 0 IN')
									var type = MapType[parts[0]];
									var idx = parseInt(parts[1]);
									if (this.page.itemCount(type) > idx){
										this.spec = new NMRSpectrum(this.page.item(idx, type));;
									}
									else {
										return [];
									}
							  }
							  else{
								// $('S M') or $('S PK') or $('S GM') or $('S GP') or $('S IN')
								  this.spec = new NMRSpectrum(nmr.activeSpectrum());
								  if(this.spec == null) return [];
								  parts[2] = parts[1];
							  }
							  try{
								  return this.specArrays(parts[2],this.spec);
							  }catch(err){
								  return [];
							  }
						}
				}
				break;
	  }
	  return this.found;
}
MNovaUtil.prototype.length = function(itemType){
	  return this.page.itemCount(MapType[itemType]);
}

MNovaUtil.prototype.specArrays = function(selector, spec){
	  spec = spec || new NMRSpectrum(nmr.activeSpectrum());
	  switch (selector)
	  {
		case 'MT': //Multiplet table
			  return this.toArray(spec.multiplets());
			  break;
		case 'PK': //Peak Table
			  return this.toArray(spec.peaks());
			  break;
		case 'GM': //GSD Multiplets Array;
			  return this.toArray(spec.gsdMultiplets());
			  break;
		case 'GP': //GSD Peaks Array
			  return this.toArray(spec.gsdPeaks());
			  break;
		case 'IN': //integrals Array
			  return this.toArray(spec.integrals());
			  break;
		default:
			  return [];
	  }
};

MNovaUtil.prototype.toArray = function(list)
{ //Used by Peaks in $.find('S PK')

	   var count = list.count;
	   var itemArray = [];
	   for(i=0; i<count; i++)
	   {
			   itemArray[i] = list.at(i);
	   }
	   return itemArray;
};

//----------------------------------------------------Dialogs UIs---------------------------------------------------------

MNovaUtil.prototype.defaultDialogs = function()
{
/// <summary>Read all Qt UIs into a object called diaogs array</summary>

	this.dialogs = new Array();
	this.dialogs['ChooseFormat'] = '<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0">  <class>Dialog</class>  <widget class="QDialog" name="Dialog">   <property name="geometry">    <rect>     <x>0</x>     <y>0</y>     <width>400</width>     <height>127</height>    </rect>   </property>   <property name="windowTitle">    <string>Choose Output Format</string>   </property>   <widget class="QGroupBox" name="groupBox">    <property name="geometry">     <rect>      <x>10</x>      <y>10</y>      <width>361</width>      <height>101</height>     </rect>    </property>    <property name="title">     <string>Select</string>    </property>    <widget class="QComboBox" name="formatBox">     <property name="geometry">      <rect>       <x>110</x>       <y>30</y>       <width>69</width>       <height>22</height>      </rect>     </property>     <property name="toolTip">      <string extracomment="Press OK to send Spectrum for registration in Data Management"/>     </property>     <item>      <property name="text">       <string>MNOVA</string>      </property>     </item>     <item>      <property name="text">       <string>PDF</string>      </property>     </item>    </widget>    <widget class="QLabel" name="label_2">     <property name="geometry">      <rect>       <x>20</x>       <y>30</y>       <width>81</width>       <height>16</height>      </rect>     </property>     <property name="text">      <string>Output Format</string>     </property>    </widget>    <widget class="QDialogButtonBox" name="buttonBox">     <property name="geometry">      <rect>       <x>10</x>       <y>60</y>       <width>341</width>       <height>32</height>      </rect>     </property>     <property name="orientation">      <enum>Qt::Horizontal</enum>     </property>     <property name="standardButtons">      <set>QDialogButtonBox::Ok</set>     </property>    </widget>   </widget>  </widget>  <resources/>  <connections>   <connection>    <sender>buttonBox</sender>    <signal>accepted()</signal>    <receiver>Dialog</receiver>    <slot>accept()</slot>    <hints>     <hint type="sourcelabel">      <x>248</x>      <y>254</y>     </hint>     <hint type="destinationlabel">      <x>157</x>      <y>274</y>     </hint>    </hints>   </connection>   <connection>    <sender>buttonBox</sender>    <signal>rejected()</signal>    <receiver>Dialog</receiver>    <slot>reject()</slot>    <hints>     <hint type="sourcelabel">      <x>316</x>      <y>260</y>     </hint>     <hint type="destinationlabel">      <x>286</x>      <y>274</y>     </hint>    </hints>   </connection>  </connections> </ui> ';
	this.dialogs['FileExists'] = '<?xml version="1.0" encoding="UTF-8"?><ui version="4.0"> <class>Dialog</class> <widget class="QDialog" name="Dialog">  <property name="geometry">   <rect>    <x>0</x>    <y>0</y>    <width>370</width>    <height>131</height>   </rect>  </property>  <property name="windowTitle">   <string>File Already Exists</string>  </property>  <property name="modal">   <bool>true</bool>  </property>  <layout class="QVBoxLayout" name="verticalLayout">   <item>    <widget class="QGroupBox" name="groupBox">     <property name="title">      <string/>     </property>     <layout class="QGridLayout" name="gridLayout">      <item row="0" column="0">       <widget class="QLabel" name="label_2">        <property name="text">         <string>Do you want to replace the existing file with this one?</string>        </property>       </widget>      </item>     </layout>    </widget>   </item>   <item>    <widget class="QDialogButtonBox" name="buttonBox">     <property name="orientation">      <enum>Qt::Horizontal</enum>     </property>     <property name="standardButtons">      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>     </property>    </widget>   </item>  </layout> </widget> <resources/> <connections>  <connection>   <sender>buttonBox</sender>   <signal>accepted()</signal>   <receiver>Dialog</receiver>   <slot>accept()</slot>   <hints>    <hint type="sourcelabel">     <x>248</x>     <y>254</y>    </hint>    <hint type="destinationlabel">     <x>157</x>     <y>274</y>    </hint>   </hints>  </connection>  <connection>   <sender>buttonBox</sender>   <signal>rejected()</signal>   <receiver>Dialog</receiver>   <slot>reject()</slot>   <hints>    <hint type="sourcelabel">     <x>316</x>     <y>260</y>    </hint>    <hint type="destinationlabel">     <x>286</x>     <y>274</y>    </hint>   </hints>  </connection> </connections></ui>';
};

